#include "settingsmanager.h"
#include <QFile>
#include <QTextStream>
#include <QSettings>

SettingsManager* SettingsManager::m_instance = NULL;

SettingsManager* SettingsManager::Instance()
{
    if(!SettingsManager::m_instance)
        SettingsManager::m_instance = new SettingsManager;
    return SettingsManager::m_instance;
}

/* m_styles[EStyleComment] = new LuaStyle(QColor(0x80, 0x80, 0x80, 255), QColor("white"), true, false);
    m_styles[EStyleString] =  new LuaStyle(QColor(0x0, 0x80, 0x0, 255), QColor("white"), false, true);
    m_styles[EStyleKeyword] = new LuaStyle(QColor(0x0, 0x0, 0x80, 255), QColor("white"), false, true);
    m_styles[EStyleNumber] = new LuaStyle(QColor(0x0, 0x0, 0x80, 255), QColor("white"), false, false);
    //m_styles[EStyleLocal] = new LuaStyle(QColor(0x0, 0x80, 0x80, 255), QColor("white"), false, false);
    m_styles[EStyleLocal] = new LuaStyle(QColor(0x0, 0x0, 0x0, 255), QColor("white"), false, false);
    //m_styles[EStyleParam] = new LuaStyle(QColor(0x0, 0x80, 0x80, 255), QColor("white"), false, true);
    m_styles[EStyleParam] = new LuaStyle(QColor(0x0, 0x00, 0x00, 255), QColor("white"), true, false);
    m_styles[EStyleError] = new LuaStyle(QColor(0xFF, 0x00, 0x00, 255), QColor("white"), false, true);
    //m_styles[EStyleGlobal] = new LuaStyle(QColor(0xFF, 0x00, 0xFF, 255), QColor("white"), false, true);
    m_styles[EStyleGlobal] = new LuaStyle(QColor(0x00, 0x00, 0x00, 255), QColor("white"), false, true);
    m_styles[EStyleStandard] = new LuaStyle(QColor(0x00, 0x00, 0xFF, 255), QColor("white"), false, true);
    m_styles[EStyleHyperlink] = new LuaStyle(QColor(0x00, 0x00, 0xFF, 255), QColor("white"), false, false);
    m_styles[EStyleErrorAnnotation] = new LuaStyle(QColor(0xFF, 0xFF, 0xFF, 255), QColor("red"), true, false);*/

SettingsManager::SettingsManager()
{
    //add settings with default values
    addSetting(SettingItem("color.foreground.default", QColor(0x0, 0x0, 0x0, 255)),
               "Default Color Foreground", "fonts");
    addSetting(SettingItem("color.background.default", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Default Color Background", "fonts");
    addSetting(SettingItem("font.default",  QFont("Monospace", 12, QFont::Normal, false)),
               "Default Font", "fonts");

    addSetting(SettingItem("color.foreground.keyword", QColor(0x0, 0x0, 0x80, 255)),
               "Keyword Color Foreground", "fonts");
    addSetting(SettingItem("color.background.keyword", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Keyword Color Background", "fonts");
    addSetting(SettingItem("font.keyword",  QFont("Monospace", 12, QFont::Bold, false)),
               "Keyword Font", "fonts");

    addSetting(SettingItem("color.foreground.comment", QColor(0x80, 0x80, 0x80, 255)),
               "Comment Color Foreground", "fonts");
    addSetting(SettingItem("color.background.comment", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Comment Color Background", "fonts");
    addSetting(SettingItem("font.comment",  QFont("Monospace", 12, QFont::Normal, true)),
               "Comment Font", "fonts");

    addSetting(SettingItem("color.foreground.string", QColor(0x0, 0x80, 0x0, 255)),
               "String Color Foreground", "fonts");
    addSetting(SettingItem("color.background.string", QColor(0xFF, 0xFF, 0xFF, 255)),
               "String Color Background", "fonts");
    addSetting(SettingItem("font.string",  QFont("Monospace", 12, QFont::Bold, false)),
               "String Font", "fonts");

    addSetting(SettingItem("color.foreground.number", QColor(0x0, 0x0, 0x80, 255)),
               "Number Color Foreground", "fonts");
    addSetting(SettingItem("color.background.number", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Number Color Background", "fonts");
    addSetting(SettingItem("font.number",  QFont("Monospace", 12, QFont::Normal, false)),
               "Number Font", "fonts");

    addSetting(SettingItem("color.foreground.local", QColor(0x0, 0x80, 0x80, 255)),
               "Local Color Foreground", "fonts");
    addSetting(SettingItem("color.background.local", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Local Color Background", "fonts");
    addSetting(SettingItem("font.local",  QFont("Monospace", 12, QFont::Normal, false)),
               "Local Font", "fonts");

    addSetting(SettingItem("color.foreground.param", QColor(0x0, 0x0, 0x0, 255)),
               "Parameter Color Foreground", "fonts");
    addSetting(SettingItem("color.background.param", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Parameter Color Background", "fonts");
    addSetting(SettingItem("font.param",  QFont("Monospace", 12, QFont::Normal, true)),
               "Parameter Font", "fonts");

    addSetting(SettingItem("color.foreground.error", QColor(0xFF, 0x00, 0x0, 255)),
               "Error Color Foreground", "fonts");
    addSetting(SettingItem("color.background.error", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Error Color Background", "fonts");
    addSetting(SettingItem("font.error",  QFont("Monospace", 12, QFont::Bold, false)),
               "Error Font", "fonts");

    addSetting(SettingItem("color.foreground.global", QColor(0x00, 0x0, 0x0, 255)),
               "Global Color Foreground", "fonts");
    addSetting(SettingItem("color.background.global", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Global Color Background", "fonts");
    addSetting(SettingItem("font.global",  QFont("Monospace", 12, QFont::Bold, false)),
               "Global Font", "fonts");

    addSetting(SettingItem("color.foreground.standard", QColor(0x0, 0x0, 0xFF, 255)),
               "Standard Libraries Color Foreground", "fonts");
    addSetting(SettingItem("color.background.standard", QColor(0xFF, 0xFF, 0xFF, 255)),
               "Standard Libraries Color Background", "fonts");
    addSetting(SettingItem("font.standard",  QFont("Monospace", 12, QFont::Bold, false)),
               "Standard Libraries Font", "fonts");

    //addSetting(SettingItem("completion.global.threshold",  2),
      //         "The minimum number of characters the user must type before a global completion is performed", "completion");
    addSetting(SettingItem("completion.global.threshold",  2),
               "Global Completion Threshold", "completion");

    //addSetting(SettingItem("color.background.editor", QColor(0xFF, 0xFF, 0xFF, 255)),
      //         "Editor's Background Color", "editor");

    addSetting(SettingItem("editor.caretlinevisible", true),
               "Caret Line Visible", "editor");

    addSetting(SettingItem("editor.caretlinecolor", QColor("gainsboro")),
               "Caret Line Color", "editor");

    addSetting(SettingItem("editor.autoindent", true),
               "Enable Auto Indentation", "editor");

    addSetting(SettingItem("editor.margincolor", QColor("gainsboro")),
               "Margin Color", "editor");

    addSetting(SettingItem("editor.showmarginnumbers", true),
               "Show Margin Numbers", "editor");

    addSetting(SettingItem("editor.tabwidth", 4),
               "Tab Width", "editor");
    //load stored settings if possible
    load();
}

QStringList &SettingsManager::getRecentProjects()
{
    return m_recentProjects;
}

void SettingsManager::addRecentProject(QString aProject)
{
    if(!m_recentProjects.contains(aProject))
        m_recentProjects.insert(0, aProject);
    m_lastProject = aProject;
    save();
}

void SettingsManager::removeRecentProject(QString aProject)
{
   if(m_recentProjects.contains(aProject))
       m_recentProjects.removeOne(aProject);
}

void SettingsManager::load()
{    
    QSettings settings("Luacode", "Luacode");
    settings.beginGroup("Application");
    m_lastProject = settings.value("last_project").toString();
    m_recentProjects = settings.value("recent_projects").toString().split(";");
    m_openedTabs = settings.value("tabs").toString().split(";");
    m_currentTab = settings.value("current_tab").toString();
    settings.endGroup();
    settings.beginGroup("Fonts");
    for(int i = 0; i < m_fontsCategory.count(); i++)
    {
        QString key = m_fontsCategory[i];
        m_settingsStore[key].read(settings);
    }
    settings.endGroup();

    settings.beginGroup("Editor");
    for(int i = 0; i < m_editorCategory.count(); i++)
    {
        QString key = m_editorCategory[i];
        m_settingsStore[key].read(settings);
    }
    settings.endGroup();

    settings.beginGroup("Completion");
    for(int i = 0; i < m_completionCategory.count(); i++)
    {
        QString key = m_completionCategory[i];
        m_settingsStore[key].read(settings);
    }
    settings.endGroup();
}

void SettingsManager::save()
{    
    QSettings settings("Luacode", "Luacode");
    settings.beginGroup("Application");
    settings.setValue("last_project", m_lastProject);
    settings.setValue("recent_projects", m_recentProjects.join(";"));
    settings.setValue("tabs", m_openedTabs.join(";"));
    settings.setValue("current_tab", m_currentTab);
    settings.endGroup();

    settings.beginGroup("Fonts");
    for(int i = 0; i < m_fontsCategory.count(); i++)
    {
        QString key = m_fontsCategory[i];
        m_settingsStore[key].write(settings);
    }
    settings.endGroup();

    settings.beginGroup("Editor");
    for(int i = 0; i < m_editorCategory.count(); i++)
    {
        QString key = m_editorCategory[i];
        m_settingsStore[key].write(settings);
    }
    settings.endGroup();

    settings.beginGroup("Completion");
    for(int i = 0; i < m_completionCategory.count(); i++)
    {
        QString key = m_completionCategory[i];
        m_settingsStore[key].write(settings);
    }
    settings.sync();
}

QString SettingsManager::getLastProject()
{
    return m_lastProject;
}


void SettingsManager::setOpenedTabs(QStringList & aTabs)
{
    m_openedTabs = aTabs;
}

void SettingsManager::getTabs(QStringList & aTabs)
{
    aTabs = m_openedTabs;
}

void SettingsManager::setCurrentTab(QString aTab)
{
    m_currentTab = aTab;
}

QString SettingsManager::getCurrentTab()
{
    return m_currentTab;
}

void SettingsManager::addSetting(SettingItem aSetting, QString aCaption, QString aCategory)
{
    m_settingsStore[aSetting.getKey()] = aSetting;
    m_settingCaptions[aSetting.getKey()] = aCaption;
    if(aCategory == "fonts")
        m_fontsCategory.append(aSetting.getKey());
    else if(aCategory == "completion")
        m_completionCategory.append(aSetting.getKey());
    else if(aCategory == "editor")
        m_editorCategory.append(aSetting.getKey());
}

SettingItem &SettingsManager::getSetting(QString aKey)
{
    if(!m_settingsStore.contains(aKey))
    {
        qDebug("Unknown setting: %s!", aKey.toLocal8Bit().constData());
    }
    return m_settingsStore[aKey];
}

void SettingsManager::setFilter(QString aFilter)
{
    m_filter = aFilter;
}


void SettingsManager::addContent(QStringList &aHtml)
{
    aHtml << "<p><h3 align=\"center\">Preferences Editor<h3></p>";
    aHtml << "<ul>";
    aHtml << "<p>Font Settings</p>";
    QString backStyle;
    QString foreStyle;
    QString backSetting;
    QString foreSetting;
    //fonts settings are condensed together (background + foreground + font)
    for(int i = 0; i < m_fontsCategory.size(); i++)
    {
        QString key = m_fontsCategory[i];
        QString caption = m_settingCaptions[key];
        if(m_filter.length() > 0 and caption.contains(m_filter, Qt::CaseInsensitive) == false)
            continue;
        if(key.contains("background"))
        {
            backStyle = m_settingsStore[key].getHtmlStyle();
            backSetting = key;
        }
        else if(key.contains("foreground"))
        {
            foreStyle = m_settingsStore[key].getHtmlStyle();
            foreSetting = key;
        }
        else
        {
            aHtml << "<li class=\"value-one\"><b>"
                  << caption
                  <<"</b>"
                  << "<span style='"
                  << backStyle
                  << foreStyle
                  << m_settingsStore[key].getHtmlStyle()
                  << "'>Example"
                  << "</span>"
                  << "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
                  << "<a href='set:" + backSetting
                  << "'>Change Background Color</a>"
                  << "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
                  << "<a href='set:" + foreSetting
                  << "'>Change Foreground Color</a>"
                  << "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
                  << "<a href='set:" + key
                  << "'>Change Font</a>"
                  <<"</li>";
        }

    }
    aHtml << "<p>Code Completion Settings</p>";
    for(int i = 0; i < m_completionCategory.size(); i++)
    {
        QString key = m_completionCategory[i];
        QString caption = m_settingCaptions[key];
        if(m_filter.length() > 0 and caption.contains(m_filter, Qt::CaseInsensitive) == false)
            continue;
        aHtml << "<li class=\"value-one\"><b>"
              << caption
              <<"</b>"
              << m_settingsStore[key].getEditorContent()
              <<"</li>";
    }
    aHtml << "<p>Editor Settings</p>";
    for(int i = 0; i < m_editorCategory.size(); i++)
    {
        QString key = m_editorCategory[i];
        QString caption = m_settingCaptions[key];
        if(m_filter.length() > 0 and caption.contains(m_filter, Qt::CaseInsensitive) == false)
            continue;
        aHtml << "<li class=\"value-one\"><b>"
              << caption
              <<"</b>"
              << m_settingsStore[key].getEditorContent()
              <<"</li>";
    }
    aHtml << "</ul>";
}


